package com.git.smp.websocket;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.activiti.engine.TaskService;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.git.smp.utils.JWTUtil;

@ServerEndpoint("/websocket/task/{token}")
@Component
public class TaskServer implements ApplicationContextAware {

	private static ApplicationContext applicationContext;

	@Autowired
	private HttpServletRequest request;

	private static Logger log = LoggerFactory.getLogger(TaskServer.class);
	private final AtomicInteger OnlineCount = new AtomicInteger(0);
	// concurrent包的线程安全Set，用来存放每个客户端对应的Session对象。
	private static Map<String, List<Session>> sessionMap = new HashMap<String, List<Session>>();

	@Resource
	TaskService taskService;

	static ObjectMapper objectMapper = new ObjectMapper();

	static {
		objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
	}

	@PostConstruct
	public void init() {
		log.info("TaskServer 加载");
	}

	/**
	 * 连接建立成功调用的方法
	 */
	@OnOpen
	public void onOpen(Session session, @PathParam("token") String token) {
		String userName = JWTUtil.getUsername(token);
		List sessions = sessionMap.get(userName);
		if (sessions == null) {
			sessions = new ArrayList<Session>();
		}
		sessions.add(session);
		sessionMap.put(userName, sessions);
		int cnt = OnlineCount.incrementAndGet(); // 在线数加1
		log.info("taskServer 有连接加入，当前连接数为：{}", cnt);
//        sendMessage(session, "连接成功");
	}

	/**
	 * 连接关闭调用的方法
	 */
	@OnClose
	public void onClose(Session session) {
		for (String userName : sessionMap.keySet()) {
			List<Session> sessions = sessionMap.get(userName);
			if (sessions.contains(session)) {
				sessions.remove(session);
			}

		}

		// SessionSet.remove(session);
		int cnt = OnlineCount.decrementAndGet();
		log.info("TaskServer 有连接关闭，当前连接数为：{}", cnt);
	}

	/**
	 * 收到客户端消息后调用的方法
	 *
	 * @param message 客户端发送过来的消息
	 */
	@OnMessage
	public void onMessage(String message, Session session) {
		log.info("TaskServer 来自客户端的消息：{}", message);
//        sendMessage(session, "收到消息，消息内容："+message);

	}

	/**
	 * 出现错误
	 *
	 * @param session
	 * @param error
	 */
	@OnError
	public void onError(Session session, Throwable error) {
		log.error("TaskServer 发生错误：{}，Session ID： {}", error.getMessage(), session.getId());
		error.printStackTrace();
	}

	/**
	 * 发送消息，实践表明，每次浏览器刷新，session会发生变化。
	 *
	 * @param session
	 * @param message
	 */
	public void sendMessage(Session session, String message) {
		try {
			session.getBasicRemote().sendText(message);
		} catch (Exception e) {
			log.error("TaskServer 发送消息出错：{}", e.getMessage());
			e.printStackTrace();
		}
	}

	/**
	 * 群发消息
	 *
	 * @param message
	 * @throws IOException
	 */
	public void broadCastInfo(String message) throws IOException {
		/*
		 * for (Session session : SessionSet) { if (session.isOpen()) {
		 * sendMessage(session, message); } }
		 */
	}

	/**
	 * 指定Session发送消息
	 *
	 * @param sessionId
	 * @param message
	 * @throws IOException
	 */

	public void SendMessage(String processId) throws IOException {
		log.info("发送消息");
		log.info(sessionMap.toString());

		Task task;
		while (true) {
			task = taskService.createTaskQuery().includeProcessVariables().processInstanceId(processId).singleResult();
			if (task != null) {
				break;
			}
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		// task.ca
		List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
		for (IdentityLink identityLink : identityLinks) {
			String userName = identityLink.getUserId();
			try {
				Map map = new HashMap();
				map.put("messageType", "01");
				map.put("processInstanceId", task.getProcessInstanceId());
				map.put("taskName", task.getName());
				map.put("taskkey", task.getTaskDefinitionKey());
				map.put("taskId", task.getId());
				map.put("duUserId", task.getAssignee());
				map.put("createDate", task.getCreateTime());
				map.put("applyUser", task.getProcessVariables().get("applyUser"));
				map.put("applyDate", task.getProcessVariables().get("applyDate"));
				map.put("qmsNo", task.getProcessVariables().get("qmsNo"));
				map.put("qmsName", task.getProcessVariables().get("qmsName"));
				map.put("sid", task.getProcessVariables().get("sid"));
				map.put("applyType", task.getProcessVariables().get("applyType"));
				// JsonSerializer<T>
				List<Session> sessions = sessionMap.get(userName);
				if (sessions != null) {
					for (Session session : sessions) {
						log.info(userName);
						sendMessage(session, objectMapper.writeValueAsString(map));
					}
				}

			} catch (IOException e) {
				log.error("", e);
			}
		}

	}
	
	
	
	/**
	 * 开发完成通知
	 *
	 * @param sessionId
	 * @param message
	 * @throws IOException
	 */

	public void SendMessage1(Task task) throws IOException {

		// task.ca
			try {
				Map map = new HashMap();
				map.put("messageType", "02");
				map.put("processId", task.getProcessInstanceId());
				map.put("duUserId", task.getAssignee());
				map.put("createDate", task.getCreateTime());
				map.put("applyUser", task.getProcessVariables().get("applyUser"));
				map.put("applyDate", task.getProcessVariables().get("applyDate"));
				map.put("qmsNo", task.getProcessVariables().get("qmsNo"));
				map.put("qmsName", task.getProcessVariables().get("qmsName"));
				map.put("id", task.getProcessVariables().get("sid"));
				map.put("applyType", task.getProcessVariables().get("applyType"));
				// JsonSerializer<T>
				log.info("流程结束通知："+task.getProcessVariables().get("applyUser"));
				List<Session> sessions = sessionMap.get( task.getProcessVariables().get("applyUser"));
				if (sessions != null) {
					for (Session session : sessions) {
						sendMessage(session, objectMapper.writeValueAsString(map));
					}
				}

			} catch (IOException e) {
				log.error("", e);
			}
		}

	
	

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

}
